
import java.net.HttpURLConnection;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URLConnection;
import java.util.LinkedList;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Creates an Event Helper that processes 1 event: Read Request, Get Data from Server, Send Response
 * @author hussein
 */
public class EventWorker extends Thread {

    private HashMapCache<URL, byte[]> cache;
    private final LinkedList<EventConnection> connectionList;
    private EventConnection event;

    public EventWorker(HashMapCache<URL, byte[]> cache, LinkedList<EventConnection> connectionList, EventConnection event) {
        super();
        this.cache = cache;
        this.connectionList = connectionList;
        this.event = event;
    }

    @Override
    public void run() {
        try {
            if (event.state == EventConnection.STATE.REQ) {
                readRequest();
            } else if (event.state == EventConnection.STATE.DATA) {
                getData();
            } else if (event.state == EventConnection.STATE.RESPONSE) {
                sendResponse();
            }
        } catch (IOException ex) {
        }
    }

    private void readRequest() throws IOException {

        event.openStreams();
        int c = 0;
        int newLineCount = 0;
        String input = "";

        while (c != -1) {
            c = event.fromClient.read();
            input = input + (char) c;

            if (c == '\n') {
                newLineCount++;

            } else if (c != '\r') {
                newLineCount = 0;
            }

            if (newLineCount >= 2) {
                break;
            }
        }
        try {
            event.request = new HTTPRequest(input);
            event.state = EventConnection.STATE.DATA;
            returnEvent();
        } catch (MalformedURLException ex) {
            //out.println(ex);
        }

    }

    private void getData() throws IOException {
        event.buffer = cache.get(event.request.getUrl());

        if (event.buffer == null) {
            URLConnection host = event.request.getUrl().openConnection();
            ByteArrayOutputStream bstream = new ByteArrayOutputStream();
            BufferedInputStream fromHost = new BufferedInputStream(host.getInputStream());

            setResponseHeader(bstream, host);

            int c = 0;
            while (c != -1) {
                c = fromHost.read();
                bstream.write(c);
            }

            event.buffer = bstream.toByteArray();
            cache.put(event.request.getUrl(), event.buffer);
            bstream.close();
            fromHost.close();
        }
        event.state = EventConnection.STATE.RESPONSE;
        returnEvent();
    }

    private void sendResponse() throws IOException {
        event.toClient.write(event.buffer);
        event.toClient.flush();
        event.closeConnection();
    }

    private void returnEvent() {
        synchronized (connectionList) {
            connectionList.addLast(event);
            connectionList.notify();
        }
    }

    private void setResponseHeader(ByteArrayOutputStream bstream, URLConnection host) throws IOException {
        int status = ((HttpURLConnection) host).getResponseCode();
        String http = "HTTP/1.0 " + status + "\r\n";
        String server = "Server: Hussein's Proxy Server\r\n";
        String date = "Date: " + host.getHeaderField("Date") + "\r\n";
        String contentType = "Content-Type: " + host.getHeaderField("Content-Type") + "\r\n";
        String closeConnection = "Connection: Close\r\n\r\n";

        bstream.write(http.getBytes());
        bstream.write(server.getBytes());
        bstream.write(date.getBytes());
        bstream.write(contentType.getBytes());
        bstream.write(closeConnection.getBytes());
    }
}
